Skip to content

Add the provider documentation set and finish the decomposition - #1047

Open
jwrosewell wants to merge 163 commits into
IABTechLab:mainfrom
jwrosewell:split/5-response-hook-docs
Open

jwrosewell wants to merge 163 commits into
IABTechLab:mainfrom
jwrosewell:split/5-response-hook-docs

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Aug 19, 2026 •

Copy link
Copy Markdown
Collaborator

This description has been edited. The documentation now describes the
provider selectors in the one configuration convention the whole stack lands,
so several table and provider names have changed. If you read an earlier
version of this text, re-read "What this pull request does". The CI matrix
change and the two small code changes are the same.

What changed in the pull request since the last version of this description:

  1. The configuration reference and the Edge Cookie guide describe [ec.hmac]
    and [ec.host_signals], not [ec.providers.hmac] and
    [ec.providers.host-signals]. The word providers is gone from the file
    and every name a person types is snake_case.
  2. The same pages describe the implementation line, which lets a deployment
    run an implementation under a name of its own, and the startup refusals
    that come with the convention, being a table the selector does not name, an
    implementation this build does not have, and a setting a provider does not
    know.
  3. The example configuration carries a commented [ec.host_signals] block
    rather than [ec.providers.host-signals].
  4. The page that states the convention on its own,
    docs/guide/configuration-rules.md,
    lands with the integration seam (Open the integration seam so a vendor module can live outside core #1094), because that is where the
    remaining provider types arrive. The pages here point at it.

Stacks on the client-set Edge Cookie value path (#1046), and depends on #1043
to #1046 together, because this pull request documents what they build. The
stack has six pull requests (#1043, #1044, #1045, #1046, #1047, #1094), each
targeting main, with this one fifth and the last of the five that decompose
the provider work in #838, as requested in the #986 review.
Compare split/4-client-resolve with split/5-response-hook-docs
to see only this pull request's change.

The design specs for the series are carried by the spec pull request (#1084),
including the two this pull request used to carry:

What this pull request does

  • The IntegrationResponseMutator response-header hook that an earlier version
    of this pull request added is not in the series. The hook had no consumer,
    and the spec set's own rule is against speculative surface. The hook returns
    with the first integration that needs one, and its spec is the starting bar
    for that design.
  • docs/guide/configuration.md
    gains the [ec] provider selector with its [ec.hmac] and
    [ec.host_signals] tables, the [device] and [geo] selectors, the
    implementation line, the assume_single_jurisdiction acknowledgment, the
    requires-signal floor on a failed geo lookup, and a section on the country
    and region rules in permissions.yaml. It also says what stops a deployment,
    being a table the selector does not name, a name this build does not have, a
    provider name outside snake_case, and a setting the provider does not know.
  • The Edge Cookie guide
    (docs/guide/ec-setup-guide.md)
    is rewritten around providers and the permission model, including the narrow
    withdrawal rules, the hardened resolve endpoint and the resolved-marker
    cookie. The setup guide, API reference, error reference, Fastly guide and
    key-rotation guide are updated to match.
  • trusted-server.example.toml
    adds a commented [ec.host_signals] block and rewrites the [device] and
    [geo] comments to say what each default does and how to override it.
  • CI runs the Axum and Cloudflare jobs in
    .github/workflows/test.yml
    on windows-latest as well as ubuntu-latest, and the Axum job also runs
    the core library's unit tests natively, because on the WebAssembly targets
    the test harness stops at the first failing test and reports the rest as
    never run.
  • Two small code changes come with the documentation. A test in
    crates/trusted-server-core/src/ec/mod.rs
    again checks that a provider receives the empty string as the client IP when
    the host cannot determine one, and
    crates/trusted-server-core/src/evidence.rs
    corrects its module documentation and moves the HostSignals trait to the
    top of the file.

What happens to #838

Once the five pull requests that decompose #838 merge, #838 is closed. It stays
open as a draft reference for the review period only.

How it was verified

Every job main's CI runs was run locally against 5406acf51, on Windows and
under WSL, and all of them passed. That covers cargo fmt --all --check,
Clippy with warnings denied on the Axum, Cloudflare, Spin and Fastly adapters,
on both wasm targets and on the four permission signal crates, the Axum,
Cloudflare and Spin adapter suites, the cross-adapter parity suite, the
benchmark smoke run, the release wasm builds for Spin and Fastly, and the CLI,
OpenRTB codegen, format-docs and template cache harness jobs that only run on
Linux. The core suite passes with 2,885 tests natively and 2,879 under Viceroy.
The head then gained the merge 65f7005c9, which touches only
tools/permissions-inspector/wasm, a crate that is deliberately its own
workspace, so no workspace job's result changes. That crate builds clean for
wasm32-unknown-unknown and is rustfmt clean.

CI on that head was green across all 22 checks, being
Run Tests,
Run Format,
Integration Tests,
Permissions Inspector
and
CodeQL Advanced.
There are 22 rather than the 20 the earlier pull requests run because this one
puts the Axum test job and the Cloudflare check job on a
[ubuntu-latest, windows-latest] matrix, so both now run on Windows as well.

On the head this pull request shows now, d11895b8e, every CI check passes: cargo test, the Axum tests on Ubuntu, the CLI tests, format-docs, the integration tests, vitest and CodeQL.

References #777 and #778. Decomposes #838. Spec baseline from #986.

@jwrosewell
jwrosewell force-pushed the split/5-response-hook-docs branch 3 times, most recently from 7ebce99 to 700c913 Compare August 25, 2026 10:51
@jwrosewell jwrosewell changed the title Add the integration response-header hook and the provider documentation set Add the provider documentation set and finish the decomposition Aug 25, 2026
@jwrosewell
jwrosewell force-pushed the split/5-response-hook-docs branch 4 times, most recently from c17a7ea to 5b63f48 Compare August 27, 2026 05:37
@jwrosewell
jwrosewell force-pushed the split/5-response-hook-docs branch from 5b63f48 to 0bab4c0 Compare August 27, 2026 15:10
jwrosewell added a commit to jwrosewell/trusted-server that referenced this pull request Aug 27, 2026
The five-PR series (IABTechLab#1043 to IABTechLab#1047) opens the identity, device and geo
seams. The nine vendor integrations already in core sit behind the
integration registry instead, which is a private table, so none of them
can move out until that table is opened.

This spec defines the one core change that opens it: public registration
builders with a second input on IntegrationRegistry, browser JavaScript
carried on the registration, startup validation as a hook, the same
treatment for auction providers and the bid renderer contract, and
neutral replacements for the two places where a vendor reaches into
core. It then sets out the migration of all nine existing integrations,
one PR each. The change is complete in itself: after it, no vendor move
needs a core change.

Written against the series' tree with the file and line references for
every claim about the current code. Documentation only.
@jwrosewell
jwrosewell force-pushed the split/5-response-hook-docs branch 2 times, most recently from 3cfe393 to 45acb97 Compare August 31, 2026 12:50
jwrosewell added a commit to jwrosewell/trusted-server that referenced this pull request Aug 31, 2026
The five-PR series (IABTechLab#1043 to IABTechLab#1047) opens the identity, device and geo
seams. The nine vendor integrations already in core sit behind the
integration registry instead, which is a private table, so none of them
can move out until that table is opened.

This spec defines the one core change that opens it: public registration
builders with a second input on IntegrationRegistry, browser JavaScript
carried on the registration, startup validation as a hook, the same
treatment for auction providers and the bid renderer contract, and
neutral replacements for the two places where a vendor reaches into
core. It then sets out the migration of all nine existing integrations,
one PR each. The change is complete in itself: after it, no vendor move
needs a core change.

Written against the series' tree with the file and line references for
every claim about the current code. Documentation only.
jwrosewell added a commit to jwrosewell/trusted-server that referenced this pull request Aug 31, 2026
The review of IABTechLab#1043 asked that spec changes land before the code that
implements them, so a divergence is a decision taken in review rather
than a ratification of something already merged. PRs IABTechLab#1043 to IABTechLab#1047
each carried the design document for their own step, and IABTechLab#1043 carried
a 607-line spec describing device providers, geo providers, the
permission model and the browser resolve endpoint, none of which is in
that PR.

Move all six series documents here, so this PR carries the complete
normative set and no code:

- 2026-07-30-pluggable-providers-design.md (from IABTechLab#1043)
- provider-code-registry.md (from IABTechLab#1043)
- 2026-07-30-permission-model-design.md (from IABTechLab#1045)
- 2026-07-30-client-cycle-ec-resolve-design.md (from IABTechLab#1046, later
  revised by IABTechLab#1047)
- 2026-07-30-integration-response-header-hook-design.md (from IABTechLab#1047)
- 2026-07-30-provider-migration-rollout-design.md (from IABTechLab#1047)

Each file is taken verbatim at the tip of the stack, so the later
revisions are preserved: the provider-switching continuity section, the
geo requires-signal floor, and the code-envelope paragraph IABTechLab#1047 added
to the client-cycle spec. The revision-record tables are unchanged. No
document's substance was edited.

The only edits are to this spec's own status line, which said the PR
adds one document and that the series specs land with IABTechLab#1047, and a
revision-record row recording the move.
@aram356

aram356 commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

The sequencing discussion for this series is on #1084. This PR is superseded rather than rejected. The design in §3.6 is accepted and most of the provider work carries over onto the reordered base. See #1084.

jwrosewell added a commit to jwrosewell/trusted-server that referenced this pull request Sep 1, 2026
The four series specs (client-cycle EC resolve, permission model,
pluggable providers, migration and rollout) each carried a Status line
saying they were implemented. The code they describe is only in PRs
IABTechLab#1043 to IABTechLab#1047 and none of those is merged, so the line read as shipped
behavior. Each now says Proposed, names the PR that carries the
implementation and states that it is not yet on main, keeping the
existing revision dates and notes.

The integration provider seam spec carried counts and line references
that do not hold on main at d516a9e. Corrected against that commit:

- Section 4 said migration_guards.rs embeds "the thirteen vendor
  files". The directory holds 23 .rs files (2 infrastructure, 6 in
  nextjs/, 2 in datadome/, 13 top-level integration modules), the guard
  embeds 20 of them and 9 of those 20 belong to the nine vendors, with
  osano.rs and the two datadome/ files absent. builders() registers 13
  integrations, which is a different 13 from the file count.
- Section 3.5 gave no counts for the prepare and finalize calls. There
  are nine production prepare_request call sites across the four
  adapters and a tenth in core, and the single production
  finalize_response call site is in core rather than in any adapter.
- Section 8 item 3 described a proxy resolving geo twice, which does
  not happen on main. The real double resolution is the adapter EC
  context build against handle_auction on POST /auction.
- Section 8 item 5 understated the Spin gap and misdescribed
  Cloudflare. Cloudflare covers every route it registers and has no
  health route, while Spin skips its first-party bindings as well as
  its inline admin stubs.
- Line references: settings.rs:166 to :215, auction/mod.rs:49 to the
  list at :51 to :53, publisher.rs:4361 to :4369.

Section 6 now requires the round trip to be proven on the Fastly
adapter, the primary deployment target, rather than on any adapter,
because Fastly has no library target and the round trip otherwise only
runs on the Axum dev server.
@jwrosewell
jwrosewell force-pushed the split/5-response-hook-docs branch 6 times, most recently from 98764db to d48c98d Compare September 1, 2026 23:04
Renames `config/permissions/vanilla.yaml` to `config/permissions/sample.yaml`
and says at the top of the file, in the guide and on the constant that the file
is for testing and evaluation only, is not a production policy and is not legal
advice. "Vanilla" described the flavour of the rules and said nothing about
whether anyone should run them, which is the thing a reader needs to know
first.

The display name becomes "Sample (testing and evaluation only)", so the
inspector's dropdown carries the warning wherever the page is opened. The
build script globs `config/permissions/*.yaml`, so its manifest picks the new
name up with no change.

`include_str!` in `permissions.rs` follows the rename. The doc comment above it
is rewrapped and loses a clause-joining semicolon. The guide gains a short
paragraph saying the same thing.

The word "vanilla" is left alone where it means plain JavaScript, in the
DataDome and Lockr script guards and in an older plan document.

Tests. `cargo fmt --all --check` is clean, the core suite passes 2,851 tests,
and `./scripts/build-inspector-wasm.sh` builds and writes a manifest reading
`{"file":"sample.yaml","name":"Sample (testing and evaluation only)"}`. The
docs Prettier configuration sets `proseWrap: preserve`, so the shorter path
cannot change the formatting.
Brings upd/split/3-permissions at a2a1dfc into split/4-client-resolve. That
renames `config/permissions/vanilla.yaml` to `config/permissions/sample.yaml`
and says in the file, in the guide and on the constant that the sample is for
testing and evaluation only, is not a production policy and is not legal
advice.

The merge had no conflicts. `trusted-server.example.toml` auto-merged, because
this branch changes other parts of the same file.

Tests. `cargo fmt --all --check` is clean and the core suite passes 2,885
tests.
configuration guide

Brings upd/split/4-client-resolve at e17090b into
split/5-response-hook-docs, which carries split/3's a2a1dfc renaming
`config/permissions/vanilla.yaml` to `config/permissions/sample.yaml`.

This branch adds the permissions paragraph in `docs/guide/configuration.md`,
which split/3 does not have, so the merge could not correct it. That sentence
now names the new path and says the sample is for testing and evaluation only
and is neither a production policy nor legal advice, matching the file header
and the permission model guide.

The merge had no conflicts. `trusted-server.example.toml` auto-merged.

Tests. `cargo fmt --all --check` is clean and the core suite passes 2,885
tests. The docs Prettier configuration sets `proseWrap: preserve`, so the
edited sentence cannot change the formatting of the file.
Every name an operator types into configuration is snake_case, so the
demonstration provider is now selected with `[ec] provider = "client_fixed"`.
The key constant, the two startup messages that spell the key, the page
script's log lines, the cargo feature comment, the provider table in AGENTS.md
and the resolve endpoint in the API reference all follow. This commit changes
only that one name.

The cargo feature that compiles the provider in keeps the name
`client-fixed-demo`, because a cargo feature name is not a configuration value.
The tsjs module id `ec_client_fixed` is unchanged as well, being already
snake_case and never compared against the key.

The old name is refused when settings load, which every adapter does through
`settings_from_config_blob` before it serves a request. The message names
`client_fixed` and says what to write, so a deployment still configured with
`client-fixed` stops at startup rather than being told to add a provider block
that this provider does not need. A block written under the old name does not
make the old name acceptable either, because the name is refused before any
block is looked for. That is a breaking change, accepted for a major release.

Tests. `cargo fmt --all -- --check` is clean and `cargo clippy -p
trusted-server-core --all-targets --all-features -- -D warnings` passes. The
core suite passes 2,886 tests and 8 doc-tests, with and without the
`client-fixed-demo` feature, the new test among them. The Axum adapter passes
62 tests, `cargo clippy-axum` is clean, and `cargo check -p
trusted-server-adapter-fastly --target wasm32-wasip1` builds. The page
script's own vitest file passes 6 tests and ESLint is clean on it.
Every provider type selects the same way, with provider in its own section,
and names its providers in snake_case. Permission signals now follow that,
so [permission_signal] sources becomes [permission_signal] provider. The key
stays an ordered list, and a configuration that leaves it out still runs
every provider the adapter links, in the order the adapter offers them.

The two hyphenated provider names become gpp_sale_opt_out and us_privacy,
while gpc and tcf are unchanged. The crates report the new identifiers, and
core's selection messages, the startup log, the module README, the guides,
the example configuration and the permissions sample follow.

sources is removed rather than accepted alongside provider, which breaks a
configuration written against the branch that introduced it. A section
carrying sources is refused when the settings are read, with a message
naming provider, on each path a deployment reads settings through, being a
TOML file, the TOML value ts config push reads, and the JSON config blob
read at startup. Reading the section by hand rather than with
deny_unknown_fields is what makes that message possible, because a derived
refusal can only name sources by declaring it as a field, and would then
offer it as a key it expects whenever it refused any other.

No provider takes settings, so a [permission_signal.<name>] block stays an
unknown field. Its refusal now says that a provider which gains settings
will take them there.

Tests cover the removed key on each of those paths, a settings block
refused as an unknown field, a list surviving a config blob round trip,
and, where the real crates are linked, the documented names selecting all
four providers in order and an old hyphenated name being refused with the
names available.
Every name an operator types into configuration is snake_case, so the built-in
host-signal provider is now selected with `[ec] provider = "host_signals"` and
configured with `[ec.providers.host_signals]`. The key constant, the serde name
of the typed block, the validation error key, the registered secret path
`ec.providers.host_signals.passphrase`, the placeholder-secret report, the two
startup messages that spell the key and the provider's own log line all follow.
This commit changes only that one name.

The `HostSignals` trait, the `host_signals` fields and arguments that carry it,
and the prose that calls this the host-signal provider are unchanged, because a
host capability is not a configuration value. The test secret-store key name
`host-signals-passphrase-key` is unchanged for the same reason, being a name an
operator picks for a secret rather than a provider name.

The Rust field name and the configuration name are now the same word, so the
`#[serde(rename)]` on the typed block goes and the field is declared the same
way as `hmac` beside it. That also retires the reason the `EcProviders`
validation keys were spelled out by hand, so the note above those keys is
rewritten to say what still holds, which is that each key has to match the
secret path `TrustedServerAppConfig::secret_fields` registers.

The old name is refused when settings load, which every adapter does before it
serves a request. The message names `host_signals` and says what to write. The
refusal comes before any block is looked for, because a block left behind under
the old name is captured as a vendor block, so the old selector would otherwise
find that block, pass the settings check, and fail later in provider resolution
with a message about an adapter that supplies no such provider. That is a
breaking change, accepted for a major release.

Tests. `cargo fmt --all -- --check` is clean and `cargo clippy -p
trusted-server-core --all-targets --all-features -- -D warnings` passes. The
core suite passes 2,764 tests and 5 doc-tests with 4 ignored, the new test among
them. The Axum adapter passes 43 tests across its three binaries, `cargo
clippy-axum` is clean, and `cargo check -p trusted-server-adapter-fastly
--target wasm32-wasip1` builds.
The Edge Cookie provider blocks move from [ec.providers.<name>] to
[ec.<name>], so identity follows the one convention every provider type
uses, where [<type>] provider = "<name>" selects and [<type>.<name>]
holds that provider's settings. The [ec.providers] table is gone, and a
configuration still carrying it is rejected with the new location in the
message.

A block exists only when the provider has settings. The built-in hmac
provider has a required passphrase, so selecting it still needs
[ec.hmac], while a provider with no settings needs no block at all. Only
the adapter that injects a provider knows whether that provider has
settings, so core no longer demands a block for a name it does not
supply itself.

A block may name the implementation it configures with
implementation = "<id>", which makes the block's own name a label of the
operator's choosing. [ec] provider = "primary" with [ec.primary] holding
implementation = "hmac" and a passphrase configures the built-in
provider under a name that means something to the deployment. Everything
that resolves the selection now reads the implementation rather than the
label, covering the built-in lookup, the matching of a provider the
adapter injects, the check that a selected implementation has the
settings it needs, and the errors. An implementation this deployment
cannot build fails startup naming the implementations it does have.

The fixed [ec] keys stay reserved and cannot name a provider, every
other key in the section has to be a table, and a key that is not one is
reported as the unknown field it almost certainly is, so a typo such as
ec_stor is still caught with a sensible message. Provider names and
implementation ids are snake_case. A block the selector does not name
still fails startup, as it did before.

Secrets follow the blocks. TrustedServerAppConfig::secret_fields now
lists ec.hmac.passphrase, and EdgeZero's path segments cannot say
"whatever name the operator chose", so core reads the labeled blocks out
of the configuration itself through the new ConfiguredSecretFields trait
and resolves their passphrases from trusted_server_secrets in the same
pass. Push-time validation, where those fields hold key names rather
than secrets, no longer runs the passphrase value check against a
labeled block's key name. The check itself is unchanged wherever
settings are loaded with their secrets resolved.

The legacy [ec] passphrase shim still works and now points at [ec.hmac].
Brings the Edge Cookie provider block layout, where each provider has its
own [ec.<name>] table and an optional implementation = "<id>" line, under
the host-signal provider rename this branch already carried. Both changes
are the same decision applied to different parts of one section, so the
host-signal provider is now selected with [ec] provider = "host_signals"
and configured in [ec.host_signals], not [ec.providers.host_signals].

Four files conflicted.

crates/trusted-server-core/src/settings.rs. split/1 replaced the typed
EcProviders struct with EcProviderBlocks, a map of the blocks written
under [ec], in which only the hmac implementation keeps typed settings
and everything else is held as the raw values an adapter reads. This
branch had added host_signals as a second typed built-in beside hmac, so
the resolution gives it the same standing in the new model rather than
demoting it to raw values. EcProviderSettings gains a HostSignals
variant, EcProviderBlock gains host_signals_settings, EcProviderBlocks
gains host_signals_blocks beside hmac_blocks, read_provider_block reads a
host_signals block into the typed config, and From<HostSignalsProviderConfig>
builds the block. The block-required check in validate_provider_selection
now covers both implementations built into core, because both take a
passphrase. The placeholder-secret report names the block the operator
wrote, as it already did for hmac. The refusal of the old host-signals
spelling is kept and its message now sends the operator to
[ec.host_signals]. That refusal moved to the top of
validate_provider_selection and now covers a block left under the old
name as well as the selector, because split/1's snake_case rule runs over
the block names first and would otherwise refuse host-signals with the
general rule instead of the message naming the spelling to write. The
tests of both branches are kept, with this branch's host-signal test
rewritten onto the new block layout.

crates/trusted-server-core/src/ec/provider.rs. Both branches edited the
resolution arms and the module documentation. build_provider keeps the
host_signals parameter this branch added, because the host-signal
provider needs a service only some hosts supply, and the host-signal arm
of resolve_named_provider now reads its settings out of the block the
selector names rather than a fixed field. BUILTIN_PROVIDER_KEYS keeps
both entries under split/1's wording, which calls them implementation
ids. The documentation keeps split/1's [ec.<name>] spelling together with
this branch's statement that the host-signal provider is built per
request.

crates/trusted-server-core/src/config.rs. The registered secret path for
the host-signal passphrase drops the removed providers segment and
becomes ec.host_signals.passphrase. Push-time validation reads the
host-signal blocks the same way it reads the hmac ones, and the reader
that finds a built-in provider configured under a label of the operator's
choosing now looks for either implementation, so a labeled host-signal
block resolves its passphrase too.

crates/trusted-server-core/src/config_payload.rs. Both branches added a
key to the test secret store. Both are kept, being separate keys serving
separate tests.

Two follow-on fixes outside the conflicts. The tests this branch had
written against the removed EcProviders type now go through a new
select_host_signals_provider test helper beside select_hmac_provider, and
the build_provider calls split/1 had reduced to two arguments take the
host_signals argument again.

Tests. cargo fmt --all -- --check is clean and cargo clippy -p
trusted-server-core --all-targets --all-features -- -D warnings passes.
The core suite passes 2,782 tests and 5 doc-tests with 4 ignored. The
Axum adapter passes 43 tests across its four binaries, cargo clippy-axum
is clean, and cargo check -p trusted-server-adapter-fastly --target
wasm32-wasip1 builds.
…it/2

Brings up the Edge Cookie provider block layout from split/1, where each
provider has its own [ec.<name>] table, together with split/2's rename of
the host-signal provider to host_signals. Both are the same decision this
branch applies to permission signals, which is that every provider name
an operator types is snake_case and a provider type is a top-level table
whose provider key selects what runs.

Nothing conflicted. The permission signal work this branch carries sits
in its own section and its own module, so the Edge Cookie section
changes merged alongside it.

One fix the merge needed. A test of the jurisdiction acknowledgment built
its stateless case by deleting the hmac provider block from the test
configuration by text, and it still named that block [ec.providers.hmac].
Under the new layout the block is [ec.hmac], so the deletion would have
matched nothing and left a provider block configured with no selector,
which the new layout rejects. The test now names the block it means.

Tests. cargo fmt --all -- --check is clean and cargo clippy -p
trusted-server-core --all-targets --all-features -- -D warnings passes.
The core suite passes 2,874 tests and 8 doc-tests with 4 ignored. The
Axum adapter passes 64 tests across its five binaries, cargo clippy-axum
is clean, and cargo check -p trusted-server-adapter-fastly --target
wasm32-wasip1 builds.
…rom split/3

Brings up the Edge Cookie provider block layout from split/1, the
host_signals rename from split/2 and the permission signal provider key
from split/3, under the client_fixed rename this branch already carried.
All four are the same decision, so this branch's demonstration provider
now sits in the same layout as the rest.

Two files conflicted.

crates/trusted-server-core/src/ec/provider.rs. Both branches added
constants and resolution arms. The client_fixed constants and its
resolution arm are kept, listed in BUILTIN_PROVIDER_KEYS beside the two
providers that derive an identifier at the edge, under split/3's wording,
which calls these implementation ids rather than names. The arm now
matches on the implementation the selected block names rather than the
selector itself, which is how the other arms read since the block layout
landed, so the demonstration provider can be configured under a label as
any other provider can.

check_named_provider_configuration needed a real decision. This branch
wrote it to answer two questions, which are whether the build compiles a
name in and whether the name needs a settings block, the second by
looking every name up in [ec.providers]. The block layout removed that
lookup and moved the block question back into the settings, where it is
now asked only of the implementations core knows take settings, because a
provider an adapter injects has its block read by that adapter and core
cannot say whether it needs one. Reinstating a block requirement for
every name would undo that, so the function keeps only the question this
branch added it for, which is whether the demonstration provider is
compiled into this build, and the settings ask the block question. The
function's own reasoning still holds for what it keeps, which is that
only the resolution knows what is compiled out.

The refusal of the old client-fixed spelling moved with it into the
settings, beside the refusal of the old host-signals spelling, and both
now run before anything else. They have to, because the block layout
holds every provider name to snake_case and both old spellings break that
rule, so leaving either refusal later meant an operator got the general
rule instead of the message naming the spelling to write. Both refusals
cover a block left behind under the old name as well as the selector,
through one names_retired_provider helper.

crates/trusted-server-core/src/settings.rs. The Ec struct keeps this
branch's resolve_allowed_origins field and loses the providers field the
block layout replaced. resolve_allowed_origins is a fixed key of the [ec]
section, so it joins EC_SECTION_KEYS, without which the section would read
it as a provider block.

Four of this branch's tests followed the new layout. The one that proves
a provider with no block validates now says why the settings no longer
demand one, the old-spelling test builds its configuration through the
[ec] section helper rather than by deleting the hmac block by text, the
missing-block error names [ec.hmac], and the stale-block test builds its
block through the shared test helper.

Tests. cargo fmt --all -- --check is clean and cargo clippy -p
trusted-server-core --all-targets --all-features -- -D warnings passes.
The core suite passes 2,909 tests and 8 doc-tests with 4 ignored. The
Axum adapter passes 64 tests across its five binaries, cargo clippy-axum
is clean, and cargo check -p trusted-server-adapter-fastly --target
wasm32-wasip1 builds.
…guides

Brings up the Edge Cookie provider block layout from split/1, the
host_signals rename from split/2, the permission signal provider key from
split/3 and the client_fixed rename from split/4. All four are the same
decision, which is that every provider name an operator types is
snake_case, a provider type is a top-level table, and a provider key
inside it selects what runs.

Nothing conflicted. The response hook and the documentation set this
branch carries sit beside the sections those renames touched.

The documentation needed the work the clean merge did not do. These
guides were written against the old layout, so they still told operators
to write a table that is now refused and to select providers by spellings
that now stop startup. The configuration guide, the Edge Cookie setup
guide, the error reference, the Fastly guide and the key rotation guide
all move from [ec.providers.hmac] to [ec.hmac], and the environment
override for that passphrase becomes
TRUSTED_SERVER__EC__HMAC__PASSPHRASE, which is the path the settings now
hold it at.

The configuration guide's [ec] reference needed more than a rename. Its
rule that every selection must have a matching block is no longer what
the code does, because a provider has a block only when it has settings,
so it now says which providers need one and which do not, and it explains
the implementation key that lets a block carry a label of the operator's
choosing. Its provider list and its validation notes follow the
snake_case names, and the resolve_allowed_origins key this stack added to
the [ec] section is documented alongside the rest.

The Edge Cookie guide named the host-signal and demonstration providers
by their old spellings throughout, including in a diagram label, and now
names them host_signals and client_fixed. The cargo feature that compiles
the demonstration provider in keeps the name client-fixed-demo, because a
cargo feature name is not a configuration value.

The example configuration's commented-out host-signal block carried both
the old table and the old name, and is now [ec.host_signals] selected by
provider = "host_signals".

Tests. cargo fmt --all -- --check is clean and cargo clippy -p
trusted-server-core --all-targets --all-features -- -D warnings passes.
The core suite passes 2,909 tests and 8 doc-tests with 4 ignored. The
Axum adapter passes 64 tests across its five binaries, cargo clippy-axum
is clean, and cargo check -p trusted-server-adapter-fastly --target
wasm32-wasip1 builds.
Four sentences in the guides joined their clauses with a semicolon, and
one table row grew past its column. They now read as one sentence each,
and the table is realigned, so the pages follow the house style the rest
of the guide follows.
Brings in the eight commits main gained since this branch was cut, of which
three touch the same code as the provider seam.

The parser-aware body hold gives every adapter a second entry point,
`build_state_with_services`, so a caller can supply the `RuntimeServices`
each request uses. The composition-root check the seam added now runs in
that function rather than in `build_state_with_settings`, and it is given
whatever provider those supplied services already carry instead of always
`None`, so a caller that resolved one is not made to resolve it twice.

On Cloudflare and Spin the state keeps both the provider this branch
resolves once at start-up and the services main lets a caller supply. The
free function this branch added is gone and its one job, handing the
resolved provider to every request, moved into `services_for_request`,
which is the method main introduced for the same purpose.

The core README this branch corrected one line of has been rewritten
wholesale by the documentation refresh, and the section that line was in no
longer exists, so main's version is taken as it stands.
Carries up the resolutions from split/1, where main's second entry point,
`build_state_with_services`, meets the composition-root provider check.

This branch had already given that check and `build_reusable_provider` a
`host_signals` argument, so each call now passes `None` for host signals and
whatever provider a caller's supplied services already carry. The free
function that handed the resolved provider to every request is gone on both
adapters and its job sits in `services_for_request`, the method main added,
which passes the settings this branch made `build_runtime_services` take.
Carries up the resolutions from split/2 and settles what main's own changes
mean for the permission model.

The adapters keep both the permission signal providers this branch resolves
at start-up and the services main lets a caller supply, and
`services_for_request` passes the providers to `build_runtime_services`, so
a request served from supplied services and one served from the request
context see the same schemes.

Main added tests for `allows_ec_creation`, `has_explicit_ec_withdrawal` and
`gate_eids_by_consent`, all three of which this branch replaced with the
permission model, so those tests name functions that no longer exist and
have not been taken. The behaviour the new one covers, stripping every EID
when personalised advertising is not permitted, is already asserted here by
`gate_eids_strips_eids_when_a_required_permission_is_unset`, which reaches
it through the resolved permissions rather than through the consent context.

The no-op HTML post processor in the registry tests goes with
`IntegrationHtmlPostProcessor`, the trait main removed in favour of
per-document stream processors.
Carries up the resolutions from split/3. Nothing on this branch touches the
code main changed, so the merge needed no decision of its own.
Carries up the resolutions from split/4.

Main's documentation refresh rewrote the section table in the configuration
guide, so its version is taken with this branch's sections added in
alphabetical order. That is device and geo, which the old table listed, and
permission_signal, which it never did.
The per-request Edge Cookie test builds AppState by hand, and the merge left
it without the field the supplied-services path added. It drives the
per-request path, so it supplies none.
Main added a Next.js auction fixture that every adapter now shares. This
branch refuses a document that configures an Edge Cookie provider without
saying where its readers are, because otherwise every request resolves at the
top of the rules tree, so the fixture acknowledges single-jurisdiction
operation the way the other fixtures on this branch do.
Main's new template cache test drives withdrawal with a Californian GPC
signal and asserts the Edge Cookie is expired. On this branch that signal
suppresses use without expiring anything, which
`finalize_gpc_suppresses_headers_but_keeps_the_cookie` states as deliberate,
because a visitor who later withdraws the opt-out keeps their identity. Only
an explicit withdrawal of device storage is destructive.

The test is about one template variant being shared across identities and
across withdrawal, not about how withdrawal is signalled, so it now says it
withdrew storage and keeps asserting the same thing. `EcContext` gains the
test constructor for saying so, since the gated one gives suppression.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants